package org.lgh.wallet.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.lgh.wallet.common.OperateTypeEnum;
import org.lgh.wallet.common.R;
import org.lgh.wallet.common.TradeTypeEnum;
import org.lgh.wallet.dto.ConsumeDTO;
import org.lgh.wallet.dto.DrawbackDTO;
import org.lgh.wallet.entity.Wallet;
import org.lgh.wallet.entity.WalletDetail;
import org.lgh.wallet.mapper.WalletMapper;
import org.lgh.wallet.service.WalletDetailService;
import org.lgh.wallet.service.WalletService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

/**
 * @author wei-xhh
 * @date 2023-02-27
 */
@Service
public class WalletServiceImpl extends ServiceImpl<WalletMapper, Wallet> implements WalletService {

    @Resource
    private WalletDetailService walletDetailService;

    @Override
    public R<Object> getByUserId(Long userId) {
        if (userId == null) {
            return R.fail("用户ID不存在");
        }
        QueryWrapper<Wallet> queryWrapper =
                new QueryWrapper<Wallet>().eq("user_id", userId);
        Wallet wallet = this.getOne(queryWrapper);
        return R.ok(wallet);
    }

    @Override
    @Transactional
    public R<Object> consume(ConsumeDTO param) {
        Long userId = param.getUserId();
        BigDecimal money = param.getMoney();
        // 根据用户ID查询钱包金额,采用了MybatisPlus的乐观锁 @Version
        QueryWrapper<Wallet> queryWrapper =
                new QueryWrapper<Wallet>().eq("user_id", userId);
        Wallet wallet = this.getOne(queryWrapper);
        BigDecimal balance = wallet.getBalance();
        // 消费后剩余金额
        BigDecimal remain = balance.subtract(money);
        // 返回1表示小于0，返回-1表示大于
        if (remain.compareTo(BigDecimal.ZERO) < 0) {
            return R.fail("金额不足,无法消费");
        }
        // 更新最新金额
        Wallet updateWallet = new Wallet();
        updateWallet.setId(wallet.getId());
        updateWallet.setBalance(remain);
        boolean b = this.updateById(updateWallet);
        if (!b) {
            return R.fail("消费失败,请联系管理员!");
        } else {
            // TODO 可以异步记录金额变动明细,目前没有
            WalletDetail walletDetail = new WalletDetail();
            walletDetail.setWalletId(updateWallet.getId());
            walletDetail.setChangeBalance(money);
            walletDetail.setTradeId(param.getTradeId());
            walletDetail.setTradeType(TradeTypeEnum.getByValue(param.getTradeType()));
            walletDetail.setOperateType(OperateTypeEnum.getByValue(param.getOperateType()));
            walletDetail.setTradeTime(param.getTradeTime());
            walletDetail.setPreBalance(balance);
            walletDetail.setBackBalance(remain);
            boolean save = walletDetailService.save(walletDetail);
            if (!save) {
                return R.fail("消费失败,请联系管理员!");
            }
        }
        return R.ok();
    }

    @Override
    @Transactional
    public R<Object> drawback(DrawbackDTO param) {
        Long tradeId = param.getTradeId();
        Long userId = param.getUserId();
        // 根据交易ID从金额变动明细中查询
        QueryWrapper<WalletDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("trade_id", tradeId);
        queryWrapper.eq("user_id", userId);
        WalletDetail detail = walletDetailService.getOne(queryWrapper);
        if (detail == null) {
            return R.fail("退款失败,查无此交易");
        }
        BigDecimal changeBalance = detail.getChangeBalance();
        // 原先金额添加10,同样有乐观锁的判断
        QueryWrapper<Wallet> query =
                new QueryWrapper<Wallet>().eq("user_id", userId);
        Wallet wallet = this.getOne(query);
        BigDecimal balance = wallet.getBalance();
        // 退款后的金额
        BigDecimal all = balance.add(changeBalance);
        Wallet w = new Wallet();
        w.setId(wallet.getId());
        w.setBalance(all);
        // 更新
        boolean b = this.updateById(w);
        if (!b) {
            return R.fail("退款失败！请联系管理员");
        } else {
            WalletDetail walletDetail = new WalletDetail();
            walletDetail.setWalletId(wallet.getId());
            walletDetail.setChangeBalance(changeBalance);
            walletDetail.setTradeId(tradeId);
            walletDetail.setTradeType(TradeTypeEnum.getByValue(param.getTradeType()));
            walletDetail.setOperateType(OperateTypeEnum.getByValue(param.getOperateType()));
            walletDetail.setTradeTime(param.getTradeTime());
            walletDetail.setPreBalance(balance);
            walletDetail.setBackBalance(all);
            boolean save = walletDetailService.save(walletDetail);
            if (!save) {
                return R.fail("退款失败！请联系管理员");
            }
        }
        return R.ok();
    }

    @Override
    public R<Object> getDetail(Long walletId) {
        if (walletId == null) {
            return R.fail("查询失败！");
        }
        QueryWrapper<WalletDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wallet_id", walletId);
        List<WalletDetail> list = walletDetailService.list(queryWrapper);
        return R.ok(list);
    }
}
